#include<iostream>
#include<assert.h>
using namespace std;

//引用

//基本语法
void test1()
{
	int a = 0;
	int& b = a;   //引用必须初始化
	int& c = b;  //int& c=a;  一个实体可以有多个引用
	int x = 0;
	//int& b = x;    引用只能对应一个实体
	a++;
	b++;
	c++;
	cout << a << " " << b <<" "<< c << endl;  //3
}

//引用做参数：1.输出型参数    2.减少拷贝，提高效率（大对象/深拷贝类对象）
void swap(int& x, int& y)
{
	int a = x;
	x = y;
	y = a;

}

//引用作返回值：减少拷贝，提高效率（大对象/深拷贝类对象）
int count1(int x)
{
	static int n = 0;
	n++;

	return n;
}

int& count2(int x)
{
	static int n = 0;
	n++;

	return n;
}

int count3(int x)
{
	int n = 0;
	n++;

	return n;
}

int& count4(int x)
{
	int n = 0;
	n++;

	return n;
}

//引用作返回值：获取返回值+修改返回值
typedef struct SList
{
	int data;
	int a[100];
}SList;

int& SListA(SList* ps, int pos)
{
	assert(pos >= 0 && pos < 100);

	return ps->a[pos];
}

//函数调用
struct A
{

	int& Count(int x)
	{
		static int n = 0;
		n++;
		return n;
	}
}a;

//常引用
void test2()
{
	//引用不可以扩大权限
	//const int a = 0;
	//int& b = a;

	//引用可以平移或者缩小权限
	int x = 0;
	int& y = x;  ///平移权限
	const int& z = x;  //缩小引用权限 不能改变z 但可以通过改变x间接改变z
	x++;
	cout << x << " " << y << " " << z << endl;
}

void test3()
{
	double d = 1.1;
	int i = d;  //发生类型转换的时候都会创建一个临时变量 临时变量具有常性
	const int& r = d;  //临时变量具有常性 引用要用const修饰才不会导致引用权限扩大

	const int& a = 10;  //常量的引用也要用const修饰
}

void test4()
{
	double dd = 1.1;
	int ii = 1;
	if (dd > ii)  //此处的ii是一个double的临时变量
	{
		cout << "xxxxx" << endl;
	}
}

int main()
{
	//test1();

	int x = 0;
	int y = 1;
	swap(x, y);
	cout << x << " " << y << endl;  //1 0

	//static修饰n  安全
	int ret1 = count1(x);  //两次拷贝 返回的是为n创建的一个临时变量拷贝给ret1
	int ret2 = count2(x);  //一次拷贝 返回的是n的引用拷贝给ret2
	int& ret3 = count2(x);  //没有拷贝 ret3是n的引用
	cout << ret1 << " " << ret2 << " " << ret3 << " " << endl;  //1 1 2

	//static不修饰n
	//返回的是为n创建的一个临时变量拷贝给ret4
	//安全
	int ret4 = count3(x);  
	//如果count4函数开辟的函数栈帧销毁后没有被清理，引用找到的就是正确的值，如果被清理，找到的就是随机值
	//不安全
	int ret5 = count4(x); 
	int& ret6 = count4(x);
	cout << ret4 << " " << ret5 <<" "<< ret6 << endl;  //1 1 -858993460

	SList plist;
	plist.data = 0;
	plist.a[plist.data] = 0;
	
	SListA(&plist, 0) = 1;
	SListA(&plist, 0) += 5;
	cout << SListA(&plist, 0) << endl; //6

	//调用函数
	cout << a.Count(0) << endl;

	//常引用
	test2();
	const int& rret = count1(1);  //count1返回的是一个n的临时变量，具有常，引用要用const修饰

	//类型转换
	test4();

	return 0;
}
